package com.bong.panpan.bongcharttools;

import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.os.Handler;
import android.support.annotation.IdRes;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.bong.panpan.bongcharttools.adapter.DeviceListAdapter;
import com.bong.panpan.bongcharttools.ble.BleDeviceState;
import com.bong.panpan.bongcharttools.ble.BleInfo;
import com.bong.panpan.bongcharttools.ble.BleLink;
import com.bong.panpan.bongcharttools.custom.MyProtocol;
import com.bong.panpan.bongcharttools.custom.SpUtil;

import static com.bong.panpan.bongcharttools.ble.BleDeviceState.DEVICE_STATE_DISLINK;

/**
 * Created by panpan on 2017/9/26.
 */

public class DeviceSelectHelper implements View.OnClickListener, BleLink.BleListener {

    Button scanBtn;
    Button refreshBtn;
    RadioButton radioButton3;
    RadioButton radioButton2;
    RadioButton radioButton1;
    RadioGroup rssiRadio;
    EditText filterEdit;
    Button clsBtn;
    ListView deviceList;
    TextView linkInfo;
    Handler handler;
    Activity activity;

    public DeviceSelectHelper(Button scanBtn,
                              Button refreshBtn,
                              RadioButton radioButton3,
                              RadioButton radioButton2,
                              RadioButton radioButton1,
                              RadioGroup rssiRadio,
                              EditText filterEdit,
                              Button clsBtn,
                              ListView deviceList,
                              TextView linkInfo,
                              Handler handler,
                              Activity activity) {
        this.scanBtn = scanBtn;
        this.refreshBtn = refreshBtn;
        this.radioButton1 = radioButton1;
        this.radioButton2 = radioButton2;
        this.radioButton3 = radioButton3;
        this.rssiRadio = rssiRadio;
        this.filterEdit = filterEdit;
        this.clsBtn = clsBtn;
        this.deviceList = deviceList;
        this.linkInfo = linkInfo;
        this.handler = handler;
        this.activity = activity;
        init();
        int id= SpUtil.getInstance().getInt("DeviceSelectHelper:rssiRadio",R.id.radioButton1);
        rssiRadio.check(id);
    }

    private DeviceListAdapter adapter;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager bluetoothManager;
    private int sortModel = 2;
    private BleLink bleLink;
    private ProgressDialog progressDialog;
    public MyProtocol protocol = new MyProtocol();
    private ScanCallback scanCallback = new ScanCallback() {
        /**
         * Callback when a BLE advertisement has been found.
         *
         * @param callbackType Determines how this callback was triggered. Could be one of
         *                     {ScanSettings#CALLBACK_TYPE_ALL_MATCHES},
         *                     {ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or
         *                     {ScanSettings#CALLBACK_TYPE_MATCH_LOST}
         * @param result       A Bluetooth LE scan result.
         */
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            BluetoothDevice device = result.getDevice();
            String mac = device.getAddress();
            String name = device.getName();
            int rssi = result.getRssi();
            BleInfo value;
            String filter = filterEdit.getText().toString();
            if (adapter.isDataExits(mac)) {
                adapter.modifyData(mac, rssi);
            } else {
                value = new BleInfo();
                value.name = name;
                value.mac = mac;
                value.rssi = rssi;
                adapter.addData(value);
            }
            listFilterDeal(filter);
        }

        /**
         * Callback when scan could not be started.
         *
         * @param errorCode Error code (one of SCAN_FAILED_*) for scan failure.
         */
        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
        }
    };

    private void bubbleSort() {
        adapter.sortData(sortModel);
    }

    private void init() {
        adapter = new DeviceListAdapter(activity);
        adapter.setClickListener(this);
        deviceList.setAdapter(adapter);
        rssiRadio.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
                switch (checkedId) {
                    case R.id.radioButton3:
                        sortModel = 0;
                        bubbleSort();
                        adapter.notifyDataSetChanged();
                        break;
                    case R.id.radioButton2:
                        sortModel = 1;
                        bubbleSort();
                        adapter.notifyDataSetChanged();
                        break;
                    case R.id.radioButton1:
                        sortModel = 2;
                        break;
                }
                SpUtil.getInstance().setInt("DeviceSelectHelper:rssiRadio",checkedId);
            }
        });
        filterEdit.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                listFilterDeal(s.toString());
            }
        });
        progressDialog = new ProgressDialog(activity);
        progressDialog.setTitle("提示");
        initBle();
    }

    private void initBle() {
        // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
        // BluetoothAdapter through BluetoothManager.
        bluetoothManager =
                (BluetoothManager) activity.getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        // Checks if Bluetooth is supported on the device.
        if (mBluetoothAdapter == null) {
            activity.finish();
            return;
        }
        mBluetoothAdapter.enable();
        bleLink = new BleLink(activity);
        bleLink.addBleListener(this);
    }

    Runnable stopScan = new Runnable() {
        @Override
        public void run() {
            if ("正在扫描".equals(scanBtn.getText().toString())) {
                scanBtn.setText("扫描");
                mBluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
            }
        }
    };

    public void beginScan() {
        if (bleLink.getDeviceState()!=DEVICE_STATE_DISLINK) {
            return;
        }
        if (scanBtn.getText().equals("扫描")) {
            scanBtn.setText("正在扫描");
            mBluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);
            handler.postDelayed(stopScan, 60000);//60s后停止扫描
        } else {

        }
    }

    public void stopScan() {
        if (bleLink.getDeviceState()!=DEVICE_STATE_DISLINK) {
            return;
        }
        if (scanBtn.getText().equals("扫描")) {

        } else {
            scanBtn.setText("扫描");
            mBluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
        }
    }

    public void scanClick(View v) {
        if (scanBtn.getText().equals("断开连接")) {
            bleLink.dislink();
            return;
        }
        if (scanBtn.getText().equals("扫描")) {
            scanBtn.setText("正在扫描");
            mBluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);
            handler.postDelayed(stopScan, 60000);//60s后停止扫描
        } else {
            scanBtn.setText("扫描");
            mBluetoothAdapter.getBluetoothLeScanner().stopScan(scanCallback);
        }
    }

    public void refreshClick(View v) {
        handler.removeCallbacks(stopScan);
        adapter.clear();
        adapter.notifyDataSetChanged();
        if (scanBtn.getText().equals("扫描")) {
            scanBtn.setText("正在扫描");
            mBluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback);
        }
        handler.postDelayed(stopScan, 60000);//60s后停止扫描
    }

    public void clearClick(View v) {
        filterEdit.setText("");
    }

    private void listFilterDeal(String filter) {
        bubbleSort();
        adapter.setFilter(filter);
        adapter.notifyDataSetChanged();
    }

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        int position = v.getId();
        BleInfo bleInfo = adapter.getItem(position);
        BluetoothDevice device = bluetoothManager.getAdapter().getRemoteDevice(bleInfo.mac);
        linkBleInfo = bleInfo;
        if (bleLink.getDeviceState() == DEVICE_STATE_DISLINK) {
            if (!bleLink.link(device)) {
                showToast("蓝牙连接出错");
            }
        } else {
            showToast("蓝牙连接忙");
        }
    }

    private void showToast(String msg) {
        Toast.makeText(activity, msg, Toast.LENGTH_LONG).show();
    }

    private BleInfo linkBleInfo;
    private BleDeviceState bleState;
    boolean isUIRun = false;
    private Runnable bleStateRunnable = new Runnable() {
        @Override
        public void run() {
            switch (bleState) {
                case DEVICE_STATE_DISLINK:
                    if (progressDialog.isShowing())
                        progressDialog.cancel();
                    linkInfo.setText("未连接设备");
                    scanBtn.setText("扫描");
                    refreshBtn.setVisibility(View.VISIBLE);
                    break;
                case DEVICE_STATE_LINKING:
                    progressDialog.setMessage("正在连接:" + linkBleInfo.name + "(" + linkBleInfo.mac + ")" + ",请稍后..");
                    if (!progressDialog.isShowing())
                        progressDialog.show();
                    linkInfo.setText("正在连接:" + linkBleInfo.name + "(" + linkBleInfo.mac + ")");
                    break;
                case DEVICE_STATE_LINKED:
                    showToast("设备已连接");
                    stopScan.run();
                    //从列表中移除已连接设备
                    //adapter.removeData(linkBleInfo.mac);
                    adapter.notifyDataSetChanged();
                    linkInfo.setText("已连接:" + linkBleInfo.name + "(" + linkBleInfo.mac + ")");
                    scanBtn.setText("断开连接");
                    refreshBtn.setVisibility(View.GONE);
                    if (progressDialog.isShowing())
                        progressDialog.cancel();
                    break;
                case DEVICE_STATE_LINKFAILED:
                    if (progressDialog.isShowing())
                        progressDialog.cancel();
                    showToast("设备连接失败:"+bleLink.getErrorMsg());
                    break;
                case DEVICE_STATE_LINKLOST:
                    if (progressDialog.isShowing())
                        progressDialog.cancel();
                    showToast("设备连接丢失:"+bleLink.getErrorMsg());
                    break;
                case DEVICE_STATE_DISCOVERING:
                    progressDialog.setMessage("发现服务:" + linkBleInfo.name + "(" + linkBleInfo.mac + ")" + ",请稍后..");
                    if (!progressDialog.isShowing())
                        progressDialog.show();
                    break;
                case DEVICE_STATE_CHARACTER:
                    progressDialog.setMessage("发现特征:" + linkBleInfo.name + "(" + linkBleInfo.mac + ")" + ",请稍后..");
                    if (!progressDialog.isShowing())
                        progressDialog.show();
                    break;
                default:
                    break;
            }
            isUIRun = false;
        }
    };

    @Override
    public void OnDeviceStateChanged(BleLink bleLink, BleDeviceState state) {
        while (isUIRun) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isUIRun = true;
        bleState = state;
        handler.post(bleStateRunnable);
    }

    @Override
    public void OnDataReceived(BleLink bleLink, byte[] data) {
        protocol.receive2(data);
    }

    public void onDestory() {
        bleLink.dislink();
    }

    public BleLink getBleLink() {
        return bleLink;
    }
}
